package com.service;

import static com.def.GenericDef.EVT_IPQC_OPE;
import static com.def.GenericDef.EVT_GROUP_ID_CHANGE;
import static com.def.GenericDef.EVT_CHNAGE_LOT;
import static com.def.GenericDef.E_READ_NOT_FOUND;
import static com.def.GenericDef.E_RET_PRD_INFO;
import static com.def.GenericDef.E_XPQCOPE_INVALID_INPUT;
import static com.def.GenericDef.E_XPQCOPE_INVALID_LOT_ID;
import static com.def.GenericDef.E_XPQCOPE_INVALID_LOT_WO_ID;
import static com.def.GenericDef.E_XPQCOPE_INVALID_PRD_STATUS;
import static com.def.GenericDef.LOT_SPLIT_0;
import static com.def.GenericDef.PROC_IN_PROCESS;
import static com.def.GenericDef.RETURN_CODE_OK;
import static com.def.GenericDef.RETURN_CODE_SET_ERROR;
import static com.def.GenericDef.RETURN_CODE_UNKNOWN;
import static com.def.GenericDef.RETURN_MESG_OK;
import static com.def.GenericDef.TRX_OUT;
import static com.def.GenericDef.T_XPQCOPE;
import static com.def.GenericDef._NORMAL;
import static com.def.GenericDef.PROC_SHTC;

import java.sql.Timestamp;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dao.IRetBoxDao;
import com.dao.IRetPrdInfoDao;
import com.dao.IRetPrdLotDao;
import com.icim.service.ICIMBaseService;
import com.model.Ret_prd_info;
import com.model.Ret_prd_lot;
import com.model.Ret_prd_lotId;
import com.rtnBean.NotFoundRtnBeen;
import com.rtnBean.SimpleRtnBeen;
import com.tx.xpqcope.XpqcopeI;
import com.tx.xpqcope.XpqcopeIA;
import com.tx.xpqcope.XpqcopeO;
import com.util.GUIDGenerator;
import com.util.MqOpe;
import com.util.Util;

@Scope("prototype")
@Service("XpqcopeService")
public class XpqcopeService extends ICIMBaseService{
	private static Logger logger = Logger.getLogger(XpqcopeService.class);
	private static String TX_NAME = T_XPQCOPE;

	private XpqcopeI inTrx;
	private XpqcopeO outTrx;
	private MqOpe mqOpe;

	private String gszMsgBuf = "";
	private Timestamp gEvtTimestamp;
	private Double gEvtTimeD;
	private String gEvtSeqID;

	@Autowired
	private IRetBoxDao retBoxDao;
	@Autowired
	private IRetPrdInfoDao retPrdInfoDao;
	@Autowired
	private IRetPrdLotDao retPrdLotDao;

	
	public String subMainProc(String strInMsg) {
		long rtnCode = _NORMAL;

		String outMsg = null;
		gszMsgBuf = "";
		gEvtTimestamp = Util.getCurrentTimestamp();
		gEvtTimeD = Util.getDoubleTime();
		gEvtSeqID = GUIDGenerator.javaGUID();
		inTrx = new XpqcopeI();
		outTrx = new XpqcopeO();
		outTrx.setTrx_id(TX_NAME);
		outTrx.setType_id(TRX_OUT);
		outTrx.setRtn_code(String.valueOf(RETURN_CODE_SET_ERROR));
		mqOpe = new MqOpe();

		try {
			inTrx = (XpqcopeI) mqOpe.inStr2Obj(strInMsg, inTrx);
			logger.info("InTrx is " + strInMsg);

			rtnCode = subMainProc2(inTrx.getAct_flg().toCharArray()[0]);
			if (rtnCode != _NORMAL) {
				TransactionAspectSupport.currentTransactionStatus()
						.setRollbackOnly();
				outTrx.setRtn_code(String.valueOf(rtnCode));
				outTrx.setRtn_mesg(gszMsgBuf);
			} else {
				outTrx.setRtn_code(String.valueOf(RETURN_CODE_OK));
				outTrx.setRtn_mesg(RETURN_MESG_OK);
				retPrdInfoDao.flushCurSession();
			}
		} catch (Exception ex) {
			TransactionAspectSupport.currentTransactionStatus()
					.setRollbackOnly();
			outTrx.setRtn_mesg(ex.toString());
			outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
			logger.error(Util.stackTraceToString(ex));
		} finally {
			outMsg = mqOpe.obj2Str(outTrx);
			return outMsg;
		}
	}

	/**
	 * All move in logic
	 * 
	 * @return
	 */
	private long subMainProc2(char actionType) {
		long lRc = _NORMAL;

		switch (actionType) {
		case 'A': {
			lRc = addIpqcResult();
			if (lRc != _NORMAL) {
				return lRc;
			}
			break;
		}
		case 'B': {
			lRc = getPrdInfo();
			if (lRc != _NORMAL) {
				return lRc;
			}
			break;
		}
		case 'C': {
			lRc = updateLotId();
			if (lRc != _NORMAL) {
				return lRc;
			}
			break;
		}
		case 'D': {
			lRc = updateGroupId();
			if (lRc != _NORMAL) {
				return lRc;
			}
			break;
		}
		default: {
			gszMsgBuf = "Invalide type input: [" + actionType + "]";
			return E_XPQCOPE_INVALID_INPUT;
		}
		}

		return lRc;
	}

	private long addIpqcResult() {

		if (inTrx.getIary_cnt() > 0 && !inTrx.getIary().isEmpty()) {
			for (XpqcopeIA xpqcopeIA : inTrx.getIary()) {
				Ret_prd_info prd = new Ret_prd_info();

				// Get
				prd = retPrdInfoDao.get(xpqcopeIA.getSht_id());
				if (null == prd) {
					gszMsgBuf = new NotFoundRtnBeen(xpqcopeIA.getSht_id(),
							Ret_prd_info.class).toString();
					return E_RET_PRD_INFO + E_READ_NOT_FOUND;
				}

				// Check
				if (!PROC_IN_PROCESS.equals(prd.getPrd_stat())) {
					gszMsgBuf = "IPQC prd must [" + PROC_IN_PROCESS
							+ "], prd [" + xpqcopeIA.getSht_id() + "] is ["
							+ prd.getPrd_stat() + "]. ";
					return E_XPQCOPE_INVALID_PRD_STATUS;
				}

				// Set
				StringBuffer prd_admin_flg_sb = new StringBuffer(prd.getPrd_admin_flg());
				String judge_grade = xpqcopeIA.getJudge_grade();
				if ("OK".equals(judge_grade)){
					prd_admin_flg_sb.setCharAt(1, 'N');
				}else if ("NG".equals(judge_grade)){
					prd_admin_flg_sb.setCharAt(1, 'Y');
				}else if ("SC".equals(judge_grade)){
					prd_admin_flg_sb.setCharAt(1, 'S');
				}
				prd.setPrd_admin_flg(prd_admin_flg_sb.toString());
				prd.setPrd_grade(xpqcopeIA.getJudge_grade());
				prd.setSht_ope_msg(xpqcopeIA.getJudge_note());
				prd.setEvt_usr(xpqcopeIA.getEvt_usr());

				prd.setEvt_cate(EVT_IPQC_OPE);
				prd.setEvt_seq_id(gEvtSeqID);
				prd.setEvt_time_d(gEvtTimeD);
				prd.setEvt_timestamp(gEvtTimestamp);
				
				outTrx.setWo_id_fk(prd.getWo_id_fk());
				outTrx.setPrd_stat(prd.getPrd_stat());
				outTrx.setCr_ope_id_fk(prd.getCr_ope_id_fk());
				outTrx.setFst_judge_timestamp(gEvtTimestamp);
				

				retPrdInfoDao.update(prd);
			}
		}

		return _NORMAL;
	}
	
	/**
	 * query prd info
	 * 
	 * author:THY
	 * 
	 * @return
	 */
	private long getPrdInfo(){
		String ret_prd_seq = inTrx.getIary().get(0).getSht_id();
		
		if (Util.isSpaceCheck(ret_prd_seq)) {
			gszMsgBuf = "Input ret_prd_seq [" + ret_prd_seq + "] is null!";
			return E_XPQCOPE_INVALID_INPUT;
		}
		
		Ret_prd_info prd = new Ret_prd_info();
		
		prd = retPrdInfoDao.get(ret_prd_seq);
		if (null == prd) {
			gszMsgBuf = new NotFoundRtnBeen(ret_prd_seq,
					Ret_prd_info.class).toString();
			return E_RET_PRD_INFO + E_READ_NOT_FOUND;
		}
		
		if(!(PROC_IN_PROCESS.equals(prd.getPrd_stat()))){
			gszMsgBuf = "产品[" + ret_prd_seq + "] 不是[INPR]状态!";
			return E_XPQCOPE_INVALID_PRD_STATUS;
		}
		outTrx.setLot_id(prd.getLot_id());
		return _NORMAL;
	}
	
	/**
	 * update lot id
	 * 
	 * author:THY
	 * 
	 * @return
	 */
	private long updateLotId (){
		String lot_id ;
		if (inTrx.getIary_cnt() > 0 && !inTrx.getIary().isEmpty()) {
			for (XpqcopeIA xpqcopeIA : inTrx.getIary()) {
				Ret_prd_info prd = new Ret_prd_info();
				// Get
				prd = retPrdInfoDao.get(xpqcopeIA.getSht_id());
				if (null == prd) {
					gszMsgBuf = new NotFoundRtnBeen(xpqcopeIA.getSht_id(),
							Ret_prd_info.class).toString();
					return E_RET_PRD_INFO + E_READ_NOT_FOUND;
				}
				
				lot_id = inTrx.getIary().get(0).getLot_id();
				
				Ret_prd_lotId nret_prd_lotId = new Ret_prd_lotId();
				nret_prd_lotId.setLot_id(lot_id);
				nret_prd_lotId.setLot_splt_id(LOT_SPLIT_0);
				Ret_prd_lot nret_prd_lot = retPrdLotDao.get(nret_prd_lotId);	
				
				Ret_prd_lotId oret_prd_lotId = new Ret_prd_lotId();
				oret_prd_lotId.setLot_id(prd.getLot_id());
				oret_prd_lotId.setLot_splt_id(LOT_SPLIT_0);
				Ret_prd_lot oret_prd_lot = retPrdLotDao.get(oret_prd_lotId);
				
				if (null != nret_prd_lot) {
					if(nret_prd_lot.getWo_id_fk().equals(oret_prd_lot.getWo_id_fk())){
						nret_prd_lot.setLot_qty(1 + nret_prd_lot.getLot_qty());
//						nret_prd_lot.setEvt_usr(inTrx.getEvt_usr());
						nret_prd_lot.setEvt_timestamp(gEvtTimestamp);
						nret_prd_lot.setEvt_time_d(gEvtTimeD);
						retPrdLotDao.update(nret_prd_lot);
						
					    oret_prd_lot.setLot_qty(oret_prd_lot.getLot_qty() - 1);
//					    oret_prd_lot.setEvt_usr(inTrx.getEvt_usr());
					    oret_prd_lot.setEvt_timestamp(gEvtTimestamp);
					    oret_prd_lot.setEvt_time_d(gEvtTimeD);
					    retPrdLotDao.update(oret_prd_lot);
					}else{
			        	gszMsgBuf = "目标批次["+lot_id+"]所属工单["+ nret_prd_lot.getWo_id_fk() + "]与原批次["+prd.getLot_id()+"]所属工单["+oret_prd_lot.getWo_id_fk()+"]不一致，无法调整!";
						return E_XPQCOPE_INVALID_LOT_WO_ID;
					}
				} else {
		        	gszMsgBuf = "目标批次["+ lot_id + "]未创建，无法调整!";
					return E_XPQCOPE_INVALID_LOT_ID;
				}
				//set new lot id
				prd.setLot_id(lot_id);
				prd.setSht_ope_msg(xpqcopeIA.getJudge_note());
				prd.setEvt_cate(EVT_CHNAGE_LOT);
				prd.setEvt_seq_id(gEvtSeqID);
				prd.setEvt_time_d(gEvtTimeD);
				prd.setEvt_timestamp(gEvtTimestamp);
				//update entity
				retPrdInfoDao.update(prd);
			}
		}
		
		return _NORMAL;
	}
	
	/**
	 * update lot id
	 * 
	 * author:THY
	 * 
	 * @return
	 */
	private long updateGroupId (){
		if (inTrx.getIary_cnt() > 0 && !inTrx.getIary().isEmpty()) {
			for (XpqcopeIA xpqcopeIA : inTrx.getIary()) {
				Ret_prd_info prd = new Ret_prd_info();

				// Get
				prd = retPrdInfoDao.get(xpqcopeIA.getSht_id());
				if (null == prd) {
					gszMsgBuf = new NotFoundRtnBeen(xpqcopeIA.getSht_id(),
							Ret_prd_info.class).toString();
					return E_RET_PRD_INFO + E_READ_NOT_FOUND;
				}
				if(PROC_SHTC.equals(prd.getPrd_stat())){
					gszMsgBuf = "产品代码[" + prd.getPrd_seq_id() + "]状态为[" + prd.getPrd_stat() + "],不允许修改组代码";
					return E_XPQCOPE_INVALID_PRD_STATUS;
				}
				if ( xpqcopeIA.getGroup_id() != null ){
					prd.setGroup_id(xpqcopeIA.getGroup_id());
				}else{
					prd.setGroup_id("");
				}
				prd.setSht_ope_msg(xpqcopeIA.getJudge_note());
				prd.setEvt_usr(xpqcopeIA.getEvt_usr());

				prd.setEvt_cate(EVT_GROUP_ID_CHANGE);
				prd.setEvt_seq_id(gEvtSeqID);
				prd.setEvt_time_d(gEvtTimeD);
				prd.setEvt_timestamp(gEvtTimestamp);
				
				outTrx.setWo_id_fk(prd.getWo_id_fk());
				outTrx.setPrd_stat(prd.getPrd_stat());
				outTrx.setCr_ope_id_fk(prd.getCr_ope_id_fk());
				outTrx.setFst_judge_timestamp(gEvtTimestamp);
				
				retPrdInfoDao.update(prd);
			}
		}
		
		return _NORMAL;
	}
	
	private SimpleRtnBeen setOutTrx() {
		SimpleRtnBeen rtn = new SimpleRtnBeen(_NORMAL);

		return rtn;
	}

}
